package org.despair2D.ui.puppet 
{
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.utils.Dictionary;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
	import org.despair2D.debug.Logger;
	import org.despair2D.renderer.IView;
	import org.despair2D.ui.core.Component;
	
	import org.despair2D.core.ns_despair;
	use namespace ns_despair;
	
	
	/**
	 * 九宫格傀儡
	 * 
	 * @usage	1. 九宫格数据量有限，所以直接使用缓存.
	 * 			2. 当宽或高未设置(<=0)时，使用原始宽高.
	 * 			3. 原始显示对象必须处于坐标原点.
	 * 			4. 所有九宫格相关数值必须为整数.
	 */
public class NineScalePuppet extends PuppetProxy
{
	
	public function NineScalePuppet() 
	{
		super()
		m_view = new NineScalePuppetComp(this);
	}
	
	
	
	final override public function get width() : Number
	{
		return m_view.width
	}
	
	final public function set width( v:Number ) : void
	{
		m_view.width = v
	}
	
	
	final override public function get height() : Number
	{
		return m_view.height
	}
	
	final public function set height( v:Number ) : void
	{
		m_view.height = v
	}

	
	final public function setSize( width:Number, height:Number ) : void
	{
		m_view.setSize(width, height)
	}
	
	
	final public function get minWidth() : Number
	{
		return m_view.minWidth
	}
	
	
	final public function get minHeight() : Number
	{
		return m_view.minHeight
	}
	
	
	
	final override ns_despair function get view() : IView
	{
		return m_view;
	}
	
	
	
	/**
	 * 设置九宫格数据
	 * @usage	该方法仅初始使用一次，无必要动态更改画像资源!!
	 * 
	 * @param	displayRef
	 */
	final public function setNineScale( displayRef:* ) : void
	{
		var key:String 
		var display:DisplayObject
		var definition:Class
		var prop:NineScaleProp
		
		if (displayRef is Class)
		{
			key         =  getQualifiedClassName(displayRef)
			definition  =  displayRef as Class
		}
		
		else if (displayRef is String)
		{
			try
			{
				key         =  displayRef
				definition  =  getDefinitionByName(key) as Class
			}
			
			catch (error:Error)
			{
				Logger.reportError(this, 'setNineScale', '显示对象类型: (' + displayRef + ')未定义 !!')
			}
		}
		
		else
		{
			Logger.reportError(this, 'setNineScale', '参数displayRef类型错误')
		}
		
		prop = m_nineScaleProps[key]
		
		if (!prop)
		{
			try
			{
				display = new definition()
			}
			
			catch (error:Error)
			{
				Logger.reportError(this, 'setNineScale', '参数定义类型错误...!')
			}
			
			prop                   =  createNineScaleProp(display)
			m_nineScaleProps[key]  =  prop
		}
		
		m_view.setNineScaleProp(prop)
	}
	
	
	
	
	final override ns_despair function recycle() : void
	{
		super.recycle();
		cachedNineScaleList[cachedNineScaleLength++] = this;
	}
	
	
	
	/**
	 * 生成九宫格画像数据
	 * @param	displayRef
	 */
	ns_despair static function createNineScaleProp( display:DisplayObject ) : NineScaleProp
	{
		// 九宫格检查
		var scaleGrid:Rectangle = display.scale9Grid;
		if (!scaleGrid)
		{
			Logger.reportError('NineScalePuppet', 'createNineScaleProp', '定义实例未定义九宫格...!');
		}
		
		// 原点定位检查
		var bounds:Rectangle = display.getBounds(display);
		if (bounds.x != 0 || bounds.y != 0)
		{
			Logger.reportError('NineScalePuppet', 'createNineScaleProp', '定义实例未位于坐标原点...!');
		}
		
		// 整值检查
		else if (!Boolean(bounds.width is int) || 
				!Boolean(bounds.height is int) ||
				!Boolean(scaleGrid.x is int) || 
				!Boolean(scaleGrid.y is int) || 
				!Boolean(scaleGrid.width is int) || 
				!Boolean(scaleGrid.height is int))
		{
			Logger.reportError('NineScalePuppet', 'createNineScaleProp', '定义实例存在非整值属性...!');
		}
		
		var prop:NineScaleProp = new NineScaleProp();
		var matrix:Matrix = new Matrix();
		var bmd:BitmapData
		
		var left:int    =  prop.left    =  scaleGrid.left
		var right:int   =  prop.right   =  scaleGrid.right
		var top:int     =  prop.top     =  scaleGrid.top
		var bottom:int  =  prop.bottom  =  scaleGrid.bottom
		var width:int   =  prop.width   =  bounds.width
		var height:int  =  prop.height  =  bounds.height
		
		// top
		bmd = new BitmapData( left, top, true, 0x0 )
		prop.sevenBmd = bmd
		bmd.draw(display);
		
		bmd = new BitmapData( right - left, top, true, 0x0 )
		prop.eightBmd = bmd
		matrix.identity()
		matrix.translate( -left, 0 )
		bmd.draw(display, matrix)
		
		bmd = new BitmapData( width - right, top, true, 0x0 )
		prop.nineBmd = bmd
		matrix.identity()
		matrix.translate( -right, 0 )
		bmd.draw(display, matrix)
		
		// middle
		bmd = new BitmapData( left, bottom - top, true, 0x0 )
		prop.fourBmd = bmd
		matrix.identity()
		matrix.translate( 0, -top )
		bmd.draw(display, matrix)
		
		bmd = new BitmapData( right - left, bottom - top, true, 0x0 )
		prop.fiveBmd = bmd
		matrix.identity()
		matrix.translate( -left, -top )
		bmd.draw(display, matrix)
		
		bmd = new BitmapData( width - right, bottom - top, true, 0x0 )
		prop.sixBmd = bmd
		matrix.identity()
		matrix.translate( -right, -top )
		bmd.draw(display, matrix)
		
		// bottom
		bmd = new BitmapData( left, height - bottom, true, 0x0 )
		prop.oneBmd = bmd
		matrix.identity()
		matrix.translate( 0, -bottom )
		bmd.draw(display, matrix)
		
		bmd = new BitmapData( right - left, height - bottom, true, 0x0 )
		prop.twoBmd = bmd
		matrix.identity()
		matrix.translate( -left, -bottom )
		bmd.draw(display, matrix)
		
		bmd = new BitmapData( width - right, height - bottom, true, 0x0 )
		prop.threeBmd = bmd
		matrix.identity()
		matrix.translate( -right, -bottom )
		bmd.draw(display, matrix)
		
		return prop
	}
	
	
	ns_despair static function getNineScalePuppet( displayRef:*, width:Number, height:Number ) : NineScalePuppet
	{
		var N:NineScalePuppet
		
		N = Boolean(cachedNineScaleLength > 0 ? cachedNineScaleLength-- : 0) ? cachedNineScaleList.pop() : new NineScalePuppet();
		N.m_view.m_currWidth   =  width
		N.m_view.m_currHeight  =  height
		N.setNineScale(displayRef)
		return N;
	}
	
	
	
	
	ns_despair static var cachedNineScaleList:Array = [];
	
	ns_despair static var cachedNineScaleLength:int;
	
	ns_despair static var m_nineScaleProps:Object =  new Object()
	
	
	ns_despair var m_view:NineScalePuppetComp
	
}

}


import flash.display.Bitmap;
import flash.display.BitmapData;
import org.despair2D.debug.Logger;
import org.despair2D.ui.puppet.PuppetCompBase
import org.despair2D.ui.puppet.IPuppet
import org.despair2D.ui.puppet.NineScalePuppet

import org.despair2D.core.ns_despair;
use namespace ns_despair;


final class NineScalePuppetComp extends PuppetCompBase
{
	
	public function NineScalePuppetComp( proxy:IPuppet )
	{
		super(proxy);
		
		m_oneBmp    =  new Bitmap()
		m_twoBmp    =  new Bitmap()
		m_threeBmp  =  new Bitmap()
		m_fourBmp   =  new Bitmap()
		m_fiveBmp   =  new Bitmap()
		m_sixBmp    =  new Bitmap()
		m_sevenBmp  =  new Bitmap()
		m_eightBmp  =  new Bitmap()
		m_nineBmp   =  new Bitmap()
		
		this.addChild(m_oneBmp);
		this.addChild(m_twoBmp);
		this.addChild(m_threeBmp);
		this.addChild(m_fourBmp);
		this.addChild(m_fiveBmp);
		this.addChild(m_sixBmp);
		this.addChild(m_sevenBmp);
		this.addChild(m_eightBmp);
		this.addChild(m_nineBmp);
	}
	
	
	
	final override public function get width() : Number
	{
		return m_currWidth
	}
	
	final override public function set width( v:Number ) : void
	{
		this.rejustImagePostion(v, m_currHeight);
		m_currWidth = v
	}
	
	
	final override public function get height() : Number
	{
		return m_currHeight
	}
	
	final override public function set height( v:Number ) : void
	{
		this.rejustImagePostion(m_currWidth, v);
		m_currHeight = v
	}
	
	
	
	final ns_despair function setSize( width:Number, height:Number ) : void
	{
		this.rejustImagePostion(width, height);
		m_currWidth   =  width
		m_currHeight  =  height
	}
	
	
	final ns_despair function setNineScaleProp( prop:NineScaleProp ) : void
	{
		if (m_prop == prop)
		{
			return
		}
		
		m_prop         =  prop
		this.left      =  prop.left
		this.right     =  prop.right
		this.top       =  prop.top
		this.bottom    =  prop.bottom
		this.m_width   =  prop.width
		this.m_height  =  prop.height
		
		m_oneBmp.bitmapData    =  prop.oneBmd
		m_twoBmp.bitmapData    =  prop.twoBmd
		m_threeBmp.bitmapData  =  prop.threeBmd
		m_fourBmp.bitmapData   =  prop.fourBmd
		m_fiveBmp.bitmapData   =  prop.fiveBmd
		m_sixBmp.bitmapData    =  prop.sixBmd
		m_sevenBmp.bitmapData  =  prop.sevenBmd
		m_eightBmp.bitmapData  =  prop.eightBmd
		m_nineBmp.bitmapData   =  prop.nineBmd
		
		m_eightBmp.x  =  m_fiveBmp.x  =  m_twoBmp.x  =  left
		m_fourBmp.y   =  m_fiveBmp.y  =  m_sixBmp.y  =  top
		
		this.rejustImagePostion(m_currWidth, m_currHeight);
	}
	
	
	final ns_despair function get minWidth() : Number
	{
		return m_width - (right - left)
	}
	
	
	final ns_despair function get minHeight() : Number
	{
		return m_height - (bottom - top)
	}
	
	
	/**
	 * 调整画像位置a
	 */
	final ns_despair function rejustImagePostion( currWidth:Number, currHeight:Number ) : void
	{
		// width
		if (currWidth <= 0)
		{
			m_eightBmp.scaleX = m_fiveBmp.scaleX = m_twoBmp.scaleX = 1
			m_nineBmp.x       = m_sixBmp.x       = m_threeBmp.x    = this.right
		}
		
		else
		{
			if (currWidth < this.minWidth)
			{
				Logger.reportWarning(this, 'rejustImagePostion', '当前宽度不可小于最小宽度.');
				currWidth = this.minWidth
			}
		
			// 852
			m_eightBmp.width = m_fiveBmp.width = m_twoBmp.width = currWidth - this.minWidth
			// 963
			m_nineBmp.x      = m_sixBmp.x      = m_threeBmp.x   = currWidth - (m_width - right)
		}
		
		// height
		if (currHeight <= 0)
		{
			m_fourBmp.scaleY = m_fiveBmp.scaleY = m_sixBmp.scaleY = 1
			m_oneBmp.y       = m_twoBmp.y       = m_threeBmp.y    = this.bottom
		}
		
		else 
		{
			if (currHeight < this.minHeight)
			{
				Logger.reportWarning(this, 'rejustImagePostion', '当前宽度不可小于最小宽度.');
				currHeight = this.minHeight
			}
		
			// 456
			m_fourBmp.height = m_fiveBmp.height = m_sixBmp.height = currHeight - this.minHeight
			// 123
			m_oneBmp.y       = m_twoBmp.y       = m_threeBmp.y    = currHeight - (m_height - bottom)
		}
	}
	

	final ns_despair override function recycle() : void
	{
		super.recycle();
		m_oneBmp.bitmapData = m_twoBmp.bitmapData = m_threeBmp.bitmapData = m_fourBmp.bitmapData = m_fiveBmp.bitmapData = m_sixBmp.bitmapData = m_sevenBmp.bitmapData = m_eightBmp.bitmapData = m_nineBmp.bitmapData = null
		m_prop = null
	}
	
	
	
	ns_despair var m_sevenBmp:Bitmap, m_eightBmp:Bitmap, m_nineBmp:Bitmap;
	
	ns_despair var m_fourBmp:Bitmap, m_fiveBmp:Bitmap, m_sixBmp:Bitmap;
	
	ns_despair var m_oneBmp:Bitmap, m_twoBmp:Bitmap, m_threeBmp:Bitmap;
	
	ns_despair var left:int, right:int, top:int, bottom:int, m_width:int, m_height:int
	
	ns_despair var m_currWidth:Number, m_currHeight:Number
	
	ns_despair var m_prop:NineScaleProp
	
}



//======================
// 九宫格画像数据
//======================
final class NineScaleProp
{
	
	
	internal var sevenBmd:BitmapData, eightBmd:BitmapData, nineBmd:BitmapData;
	
	internal var fourBmd:BitmapData, fiveBmd:BitmapData, sixBmd:BitmapData;
	
	internal var oneBmd:BitmapData, twoBmd:BitmapData, threeBmd:BitmapData;
	
	internal var left:int, right:int, top:int, bottom:int, width:int, height:int
	
}